package org.cjstudio.holypoopsgrs.test;


import javax.annotation.Resource;

import org.cjstudio.holypoopsgrs.model.UserProfile;
import org.cjstudio.holypoopsgrs.server.Repository;
import org.cjstudio.holypoopsgrs.server.Repository.UpdateParams;
import org.cjstudio.holypoopsgrs.test.util.SampleData;
import org.cjstudio.holypoopsgrs.test.template.SpringAppEngineTest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@ContextConfiguration("/testContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest1 extends SpringAppEngineTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

	}

	@Override
	@After
	public void tearDown() throws Exception {
		super.tearDown();

	}


	@Resource
	private Repository<UserProfile> userProfileRepository = null;

	@Test
	public void injectionTest() {
		// Assert the cached 'userProfileRepository' is injdected.
		Assert.assertNotNull(userProfileRepository);
	}

	@Test
	public void simpleInOutTest() {
		//store sample profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//retrieve the profile and compare
		UserProfile storedProfile = userProfileRepository.retrieve(profile.udid);
		System.out.println("Sample Profile : " + profile);
		System.out.println("Stored Profile : " + storedProfile);

		//Both topTenRecords have same content in different order.
		Assert.assertTrue(storedProfile.topTenRecords.containsAll(profile.topTenRecords));

		profile.topTenRecords = null;
		storedProfile.topTenRecords = null;
		Assert.assertEquals(profile, storedProfile);
	}

	@Test
	public void simpleUpdateTest_success() {
		//store and retrieve sample profile
		UserProfile profile = SampleData.getSampleProfile(2);
		userProfileRepository.create(profile);
		profile = userProfileRepository.retrieve(profile.udid);
		System.out.println("Sample Profile : " + profile);

		//revise and update the profile
		//		profile = SampleData.getRevisedProfile(profile);
		//		System.out.println("Revised Profile(1) : " + profile);
		//		userProfileRepository.update(profile);

		/* Update Method 1 (Low Level) */
		UpdateParams<UserProfile> updateParams = userProfileRepository.update(profile.udid);
		Assert.assertNotNull(updateParams);
		profile = SampleData.getRevisedProfile(updateParams.obj);
		updateParams.pm.close();

		/* Update Method 2 */
		// TODO generate dirty map


		System.out.println("Revised Profile : " + profile);

		//retrieve the profile and compare
		UserProfile updatedProfile = userProfileRepository.retrieve(profile.udid);
		System.out.println("Updated Profile : " + updatedProfile);

		//Both topTenRecords have same content in different order.
		Assert.assertTrue(updatedProfile.topTenRecords.containsAll(profile.topTenRecords));

		profile.topTenRecords = null;
		updatedProfile.topTenRecords = null;
		Assert.assertEquals(profile, updatedProfile);
	}

	@Test
	public void simpleUpdateTest_fail() {
		//store and retrieve sample profile
		UserProfile profile = SampleData.getSampleProfile(2);
		userProfileRepository.create(profile);
		profile = userProfileRepository.retrieve(profile.udid);
		System.out.println("Sample Profile : " + profile);
		System.out.println("Sample Profile TopTenRecords : " + profile.topTenRecords.toString());
		System.out.println();

		//revise and update the profile
		//		profile = SampleData.getRevisedProfile(profile);
		//		System.out.println("Revised Profile(1) : " + profile);
		//		userProfileRepository.update(profile);

		/* Update Method 1 (Low Level) */
		UpdateParams<UserProfile> updateParams = userProfileRepository.update(SampleData.getSampleProfile(3).udid);
		Assert.assertNull(updateParams);
	}

	@Test
	public void simpleDeleteTest1_success() {
		//store sample profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//retrieve the profile and compare
		UserProfile storedProfile = userProfileRepository.retrieve(profile.udid);
		boolean result = userProfileRepository.delete(storedProfile);
		Assert.assertTrue(result);

		UserProfile deletedProfile = userProfileRepository.retrieve(storedProfile.udid);
		Assert.assertNull(deletedProfile);
	}

	@Test
	public void simpleDeleteTest1_fail() {
		//store sample profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//retrieve the profile and compare
		UserProfile storedProfile = userProfileRepository.retrieve(profile.udid);
		boolean result = userProfileRepository.delete(SampleData.getSampleProfile(1));
		Assert.assertFalse(result);

		UserProfile notDeletedProfile = userProfileRepository.retrieve(storedProfile.udid);
		Assert.assertNotNull(notDeletedProfile);
	}


	@Test
	public void simpleDeleteTest2_success() {
		//store sample profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//retrieve the profile and compare
		UserProfile storedProfile = userProfileRepository.retrieve(profile.udid);
		boolean result = userProfileRepository.delete(storedProfile.udid);
		Assert.assertTrue(result);

		UserProfile deletedProfile = userProfileRepository.retrieve(storedProfile.udid);
		Assert.assertNull(deletedProfile);
	}

	@Test
	public void simpleDeleteTest2_fail() {
		//store sample profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//retrieve the profile and compare
		UserProfile storedProfile = userProfileRepository.retrieve(profile.udid);
		boolean result = userProfileRepository.delete(SampleData.getSampleProfile(1));
		Assert.assertFalse(result);

		UserProfile notDeletedProfile = userProfileRepository.retrieve(storedProfile.udid);
		Assert.assertNotNull(notDeletedProfile);
	}
}
